package com.market.member.service.impl;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.channel.service.ICountInfoService;
import com.block.channelext.enums.ActionTypeEnum;
import com.block.channelext.service.IActionInfoService;
import com.block.common.bean.CommonParam;
import com.block.common.bean.SessionBean;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.constant.SysConstant;
import com.block.common.enums.BaseTypeInfoEnum;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.model.dto.CommonReqDTO;
import com.block.common.model.dto.CountInfoDTO;
import com.block.common.model.dto.LoginReqDTO;
import com.block.common.service.IAddressInfoService;
import com.block.common.service.ILoginSessionService;
import com.block.common.service.IPackageInfoService;
import com.block.common.service.LogFactory;
import com.block.common.vo.ResponseVo;
import com.block.datapush.model.result.SpePushResut;
import com.block.datapush.service.IDataPushService;
import com.block.db.entity.*;
import com.block.db.mapper.MemberExtInfoMapper;
import com.block.db.mapper.MemberInfoMapper;
import com.market.member.factory.LoginTypeFactory;
import com.market.member.model.dto.LoginResultDTO;
import com.market.member.model.dto.MemberInfoDTO;
import com.market.member.model.vo.UserInfoVO;
import com.market.member.service.IMemberExtInfoService;
import com.market.member.service.IMemberInfoService;
import org.slf4j.Logger;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 
 * @since 2022-07-22
 */
@Service
public class MemberInfoServiceImpl extends ServiceImpl<MemberInfoMapper, MemberInfo> implements IMemberInfoService {

    private static Logger log = LogFactory.getCommLog();

    @Autowired
    ILoginSessionService loginSessionService;
    @Resource
    MemberInfoMapper memberInfoMapper;
    @Resource
    MemberExtInfoMapper memberExtInfoMapper;
    @Autowired
    IMemberExtInfoService memberExtInfoService;
    @Autowired
    ICountInfoService countInfoService;
    @Autowired
    IDataPushService dataPushService;
    @Autowired
    IActionInfoService actionInfoService;
    @Autowired
    NotifyExceptionService notifyExceptionService;
    @Autowired
    IAddressInfoService addressInfoService;


    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public ResponseVo toLogin(LoginReqDTO loginReqDTO, CommonReqDTO commonReqDTO, CommonParam commonParam){

        ResponseVo responseVo = LoginTypeFactory.getService(loginReqDTO.getLoginType()).toLogin(loginReqDTO);
        if (!AppRspCodeConstant.SUCCESS.equals(responseVo.getRspCode())){
            log.info("【用户登录】登录失败【result】{}", JSON.toJSONString(responseVo));
            return responseVo;
        }

        LoginResultDTO loginResultDTO = responseVo.getData().toJavaObject(LoginResultDTO.class);
        // 返回用户的个人信息
        SessionBean sessionBean = loginSessionService.loginSession(loginResultDTO.getUid(), loginReqDTO, commonReqDTO);
        if (sessionBean == null){
            return new ResponseVo(AppRspCodeConstant.LOGIN_ERROR, "登录失败，请重试", "");
        }

        // 统计信息(统计 登陆/注册数据)
        if (loginResultDTO.isNewMember() && !ObjectUtil.equals(Integer.valueOf(3), loginResultDTO.getMemberType())){
            actionInfoService.actionHandle(commonParam.getChannelCode(), ActionTypeEnum.REGISTER, commonParam, sessionBean.getUid());
        }
        countInfoService.countLoginAndRegisterDataInfo(commonReqDTO.getReqChannelCode(), loginResultDTO.isNewMember(), loginResultDTO.getMemberType(), true);

        // loginsession
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setToken(sessionBean.getToken());
        userInfoVO.setUid(String.valueOf(sessionBean.getUid()));
        userInfoVO.setUsername(sessionBean.getUsername());

        userInfoVO.setChannelCode(sessionBean.getChannelCode());
        userInfoVO.setChannelName(sessionBean.getChannelName());
        userInfoVO.setUserRegDate(sessionBean.getUserRegDate());
        userInfoVO.setUserLoginDate(sessionBean.getUserLoginDate());

        userInfoVO.setAuthFlag(sessionBean.getAuthFlag());

        return new ResponseVo(AppRspCodeConstant.SUCCESS, userInfoVO);
    }

    /**
     * 更新用户信息
     * @param uid
     * @param jsonObject
     * @return
     */
    @Override
    public ResponseVo updateMemberInfo(Long uid, JSONObject jsonObject, CommonParam commonParam, ApplicationInfo applicationInfo){

        jsonObject.put("reqChannelCode", commonParam.getChannelCode());
        jsonObject.put("reqChannelName", commonParam.getChannelName());

        ResponseVo responseVo = ((IMemberInfoService) AopContext.currentProxy()).updateMemberInfoHandle(uid, jsonObject, applicationInfo);
        if (!StrUtil.equals(responseVo.getRspCode(), AppRspCodeConstant.SUCCESS)){
            return responseVo;
        }

        JSONObject resultData = responseVo.getData();
        boolean isNewMember = resultData.getBoolean("isNewMember");
        boolean isGoodAuth = resultData.getBoolean("isGoodAuth");

        // 新用户统计
        if (isNewMember){

            // 统计填写认证信息的用户信息
            // 请求渠道（统计）
            CountInfoDTO countInfoDTO = new CountInfoDTO(commonParam.getChannelCode());
            countInfoDTO.setAuthCount(1);
            if (isGoodAuth){
                countInfoDTO.setAuthGoodCount(1);
            }

            countInfoService.calculateDataInfo(countInfoDTO);

            /**
             * 用户信息认证之后，进行操作上报（信息流 相关渠道的上报）
             */
            actionInfoService.actionHandle(commonParam.getChannelCode(), ActionTypeEnum.AUTH, commonParam, uid);
        }

        JSONObject returnData = new JSONObject();
        returnData.put("newNumber", isNewMember);

        // 新用户 商户撞库
        if (isNewMember){
            try {
                SpePushResut spePushResut = dataPushService.memberCheckHandle(uid);
                returnData.put("spePushResut", spePushResut);
            }catch (Exception exception){
                exception.printStackTrace();
                notifyExceptionService.notifyNoticeInfo("pushData", "推送表单信息","推送发生异常 uid:" + uid, exception);
            }
        }
        return new ResponseVo(AppRspCodeConstant.SUCCESS, returnData);
    }

    /**
     * @param uid
     * @param jsonObject
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public ResponseVo updateMemberInfoHandle(Long uid, JSONObject jsonObject, ApplicationInfo applicationInfo) {

        MemberInfo memberInfo = memberInfoMapper.getMemberInfoByUidLock(uid);

        MemberInfoDTO memberInfoDTO = JSON.parseObject(jsonObject.toJSONString(), MemberInfoDTO.class);
        log.info("【更新用户信息】【uid】{}【memberInfoDTO】{}", uid, JSON.toJSONString(memberInfoDTO));

        boolean isNewMember = false;
        boolean isGoodAuth = false;
        MemberExtInfo memberExtInfo = memberExtInfoMapper.getMemberExtInfoByUidLock(uid);
        if (ObjectUtil.isEmpty(memberExtInfo)){
            isNewMember = true;
        }

        MemberExtInfo updateExtInfo = new MemberExtInfo();
        updateExtInfo.setUid(uid);

        updateExtInfo.setDateInfo(LocalDate.now().toString());
        updateExtInfo.setAppCode(applicationInfo.getAppCode());
        updateExtInfo.setAppName(applicationInfo.getAppName());
        updateExtInfo.setAppType(applicationInfo.getAppType());

        try {
            updateExtInfo.setAge(IdcardUtil.getAgeByIdCard(memberInfoDTO.getIdCard()));
        }catch (Exception exception){
            exception.printStackTrace();
        }

        try {
            updateExtInfo.setSex(IdcardUtil.getGenderByIdCard(memberInfoDTO.getIdCard()));
        }catch (Exception exception){
            exception.printStackTrace();
        }

        updateExtInfo.setReqIp(memberInfoDTO.getReqIp());

        String provinceCode = StrUtil.fillAfter(memberInfoDTO.getProvinceCode(), '0', 6);
        updateExtInfo.setProvinceCode(provinceCode);

        String cityCode = StrUtil.fillAfter(memberInfoDTO.getCityCode(), '0', 6);
        updateExtInfo.setCityCode(cityCode);

        AddressInfo provinceInfo = addressInfoService.getAddressInfoByCode(provinceCode);
        AddressInfo cityInfo = addressInfoService.getAddressInfoByCode(cityCode);
        if (ObjectUtil.isNotEmpty(provinceInfo)){
            updateExtInfo.setProvince(provinceInfo.getName());
        }else{
            String msg = StrUtil.format("{}|{}", memberInfoDTO.getAddress(), provinceCode);
            notifyExceptionService.notifyNoticeInfo("AddressInfo ERROR", "省份信息为空", msg, null);
        }

        if (ObjectUtil.isNotEmpty(cityInfo)){
            updateExtInfo.setCity(cityInfo.getName());
        }else{
            String msg = StrUtil.format("{}|{}", memberInfoDTO.getAddress(), cityCode);
            notifyExceptionService.notifyNoticeInfo("AddressInfo ERROR", "城市信息为空", msg, null);
        }

        updateExtInfo.setUsername(memberInfoDTO.getUsername());
        updateExtInfo.setIdCard(memberInfoDTO.getIdCard());
        updateExtInfo.setMobile(memberInfo.getMobile());
        updateExtInfo.setMobileMd5(SecureUtil.md5(memberInfo.getMobile()).toLowerCase());

        updateExtInfo.setLoanAmount(ObjectUtil.isEmpty(memberInfoDTO.getLoanAmount())?BaseTypeInfoEnum.LoanAmount.la001.getValue():memberInfoDTO.getLoanAmount());
        updateExtInfo.setLoanTime(ObjectUtil.isEmpty(memberInfoDTO.getLoanTime())?BaseTypeInfoEnum.LoanTime.lt001.getValue():memberInfoDTO.getLoanTime());
        updateExtInfo.setZhimaScore(ObjectUtil.isEmpty(memberInfoDTO.getZhimaScore())?BaseTypeInfoEnum.ZhimaScore.zm002.getValue():memberInfoDTO.getZhimaScore());
        updateExtInfo.setGjj(ObjectUtil.isEmpty(memberInfoDTO.getGjj())?BaseTypeInfoEnum.Gjj.gjj001.getValue():memberInfoDTO.getGjj());
        updateExtInfo.setSalary(ObjectUtil.isEmpty(memberInfoDTO.getSalary())?BaseTypeInfoEnum.Salary.sl002.getValue():memberInfoDTO.getSalary());

        updateExtInfo.setHouse(ObjectUtil.isEmpty(memberInfoDTO.getHouse())?BaseTypeInfoEnum.House.hu001.getValue():memberInfoDTO.getHouse());
        updateExtInfo.setJob(ObjectUtil.isEmpty(memberInfoDTO.getJob())?BaseTypeInfoEnum.Job.job001.getValue():memberInfoDTO.getJob());
        updateExtInfo.setXueli(ObjectUtil.isEmpty(memberInfoDTO.getXueli())?BaseTypeInfoEnum.XueLi.xl001.getValue():memberInfoDTO.getXueli());
        updateExtInfo.setPurpose(ObjectUtil.isEmpty(memberInfoDTO.getPurpose())?BaseTypeInfoEnum.Purpose.pu003.getValue():memberInfoDTO.getPurpose());
        updateExtInfo.setCar(ObjectUtil.isEmpty(memberInfoDTO.getCar())?BaseTypeInfoEnum.Car.car001.getValue():memberInfoDTO.getCar());
        updateExtInfo.setYuqi(ObjectUtil.isEmpty(memberInfoDTO.getYuqi())?BaseTypeInfoEnum.Yuqi.yq002.getValue():memberInfoDTO.getYuqi());
        updateExtInfo.setEnterpriseOwner(ObjectUtil.isEmpty(memberInfoDTO.getEnterpriseOwner())?BaseTypeInfoEnum.EnterpriseOwner.eo001.getValue():memberInfoDTO.getEnterpriseOwner());

        updateExtInfo.setShebao(ObjectUtil.isEmpty(memberInfoDTO.getShebao())?BaseTypeInfoEnum.SheBao.sb001.getValue():memberInfoDTO.getShebao());
        updateExtInfo.setBaodan(ObjectUtil.isEmpty(memberInfoDTO.getBaodan())?BaseTypeInfoEnum.BaoDan.bd001.getValue():memberInfoDTO.getBaodan());
        updateExtInfo.setBaitiao(ObjectUtil.isEmpty(memberInfoDTO.getBattiao())?BaseTypeInfoEnum.Baitiao.bt002.getValue():memberInfoDTO.getBattiao());
        updateExtInfo.setHuabei(ObjectUtil.isEmpty(memberInfoDTO.getHuabei())?BaseTypeInfoEnum.Huabei.hb002.getValue():memberInfoDTO.getHuabei());

        String reqChannelCode = jsonObject.getString("reqChannelCode");
        String reqChannelName = jsonObject.getString("reqChannelName");
        updateExtInfo.setChannelCode(reqChannelCode);
        updateExtInfo.setChannelName(reqChannelName);

        boolean extRes = memberExtInfoService.saveOrUpdate(updateExtInfo);
        if (!extRes){
            log.error("【更新用户信息】更新用户认证信息失败【uid】{}", uid);
            return new ResponseVo(AppRspCodeConstant.UPDATE_USER_INFO_ERROR, "上传用户信息失败，请重试", "");
        }

            // 更新用户姓名和身份证号
        MemberInfo updateEntry = new MemberInfo();
        updateEntry.setUid(memberInfo.getUid());
        updateEntry.setUsername(memberInfoDTO.getUsername());
        updateEntry.setIdCard(memberInfoDTO.getIdCard());
        updateEntry.setExtInfoFlag(1);
        boolean res = this.updateById(updateEntry);
        if (!res){
            log.error("【更新用户信息】更新用户基本信息失败【uid】{}", uid);
            return new ResponseVo(AppRspCodeConstant.UPDATE_USER_INFO_ERROR, "上传用户信息失败，请重试", "");
        }
        log.info("【更新用户信息】更新完成【uid】{}【username】{}【mobile】{}", uid, memberInfoDTO.getUsername(), memberInfoDTO.getIdCard());

        if (StrUtil.equals(BaseTypeInfoEnum.House.hu002.getValue(), updateExtInfo.getHouse()) ||
                StrUtil.equals(BaseTypeInfoEnum.Car.car002.getValue(), updateExtInfo.getCar()) ||
                StrUtil.equals(BaseTypeInfoEnum.Gjj.gjj002.getValue(), updateExtInfo.getGjj())){
            isGoodAuth = true;
        }

        JSONObject resultData = new JSONObject();
        resultData.put("isNewMember", isNewMember);
        resultData.put("isGoodAuth", isGoodAuth);
        return new ResponseVo(AppRspCodeConstant.SUCCESS, resultData);
    }

    @Autowired
    IPackageInfoService packageInfoService;

    @Override
    public ResponseVo getUserInfo(Long uid, String appId) {

        MemberInfo memberInfo = memberInfoMapper.getMemberInfoByUidLock(uid);
        PackageInfo packageInfo = packageInfoService.getEntryByAppId(appId);

        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setUid(String.valueOf(memberInfo.getUid()));
        userInfoVO.setUsername(DesensitizedUtil.chineseName(memberInfo.getUsername()));
        userInfoVO.setMobile(DesensitizedUtil.mobilePhone(memberInfo.getMobile()));
        userInfoVO.setChannelCode(memberInfo.getChannelCode());
        userInfoVO.setAuthFlag(memberInfo.getExtInfoFlag());

        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(userInfoVO));

        return new ResponseVo(AppRspCodeConstant.SUCCESS, jsonObject);
    }
}
